#include <iostream>
#include <functional>
#include <atomic>
#include <thread>

using namespace std;

class ZeroEvenOdd
{
private:
    int n;
    atomic<int> count;
    atomic<int> flag;
    atomic<bool> finished;

public:
    ZeroEvenOdd(int n)
    {
        this->n = n;
        this->count = n;
        this->flag = 0;
        this->finished = false;
    }

    // printNumber(x) outputs "x", where x is an integer.
    void zero(function<void(int)> printNumber)
    {
        while (count.load() > 0)
        {
            while (flag.load() != 0)
                if (finished.load())
                    return;
            if (count.load() <= 0)
                return;
            printNumber(0);
            if (count.load() % 2 == 0)
                flag++;
            else
                flag--;
        }
        finished = true;
    }

    void even(function<void(int)> printNumber)
    {
        while (count.load() > 0)
        {
            while (flag.load() >= 0)
                if (finished.load())
                    return;
            printNumber(n - count + 1);
            count--;
            flag++;
        }
        finished = true;
    }

    void odd(function<void(int)> printNumber)
    {
        while (count.load() > 0)
        {
            while (flag.load() <= 0)
                if (finished.load())
                    return;
            printNumber(n - count + 1);
            count--;
            flag--;
        }
        finished = true;
    }
};
int main()
{
    cout << "Code1116" << endl;
    ZeroEvenOdd *z = new ZeroEvenOdd(5);
    function<void(int)> printNumber = [](int n)
    { cout << n; };
    thread t1(bind(&ZeroEvenOdd::zero, z, printNumber));
    thread t2(bind(&ZeroEvenOdd::odd, z, printNumber));
    thread t3(bind(&ZeroEvenOdd::even, z, printNumber));
    t1.join();
    t2.join();
    t3.join();
    return 0;
}